#include "HashTable.h"

HashTable *create(int size) {
    HashTable *fresh = malloc(sizeof(HashTable));
    assert(fresh != 0);

    fresh->data = malloc(8);
    assert(fresh->data != 0);

    for(int i = 0; i < size; ++i) {
        fresh->data[i] = NULL;
    }

    fresh->size = size;

    return fresh;
}

void destroy(HashTable *hashTable) {
    for(int i = 0; i < hashTable->size; ++i) {
        KeyValue *keyValue = hashTable->data[i];
        while (keyValue) {
            KeyValue *next = keyValue->next;
            free(keyValue->key);
            free(keyValue->value);
            free(keyValue->next);
            free(keyValue);
            keyValue = next;
        }
    }
    free(hashTable->data);
    free(hashTable);
}

int hash(const char *key, const int m) {
    int hash = 0;

    for (int i = 0; i < key[i] != '\0'; ++i) {
        hash = hash * 31 + key[i];
    }

    return abs(hash % m);
}

void printDebug(HashTable *table) {
    for (int i = 0; i < table->size; ++i) {
        if (table->data[i] == NULL) {
            printf("%d:\n", i);
        } else {
            printf("%s: %s\n", table->data[i]->key, table->data[i]->value);
        }
    }
    printf("===================\n");
}

bool exists(const HashTable *table, const char *key) {
    return get(table, key) != NULL;
}

KeyValue *get(const HashTable *table, const char* key) {
    int index = hash(key, table->size);

    KeyValue *kv = table->data[index];
    while (kv) {
        if (strcmp(kv->key, key) == 0) {
            return kv;
        }
        kv = kv->next;
    }
    return NULL;
}

void add(HashTable *table, KeyValue *object) {
    KeyValue *kvGet = get(table, object->key);
    if (kvGet != NULL) {
        free(kvGet->value);
        kvGet->value = strdup(object->value);
    } else {
        int index = hash(object->key, table->size);
        object->next = table->data[index];
        table->data[index] = object;
    }
}
